package tutorial06.utils;

import java.util.LinkedList;

import objLoader.math.Matrix;
import objLoader.math.Vertex3f;

public class ModelViewMatrix {

	private Matrix matrix=new Matrix();
	private Vertex3f position=new Vertex3f();

	private LinkedList<Matrix> stackM=new LinkedList<Matrix>();
	private LinkedList<Vertex3f> stackP=new LinkedList<Vertex3f>();
	
	public ModelViewMatrix() {
		loadIdentity();
	}
	
	public void loadIdentity(){
		matrix.set(Matrix.getIdentity());
		position.set(0, 0, 0);
	}

	private void applyM(Matrix m) {
		/* Implements M=(M*(newM*P))+T
		 */
		matrix.set(matrix.Mult(m));
	}
	
	public void rotateX(float angle){
		Matrix m=Matrix.getRotationX(angle);
		applyM(m);
	}

	public void rotateY(float angle){
		Matrix m=Matrix.getRotationY(angle);
		applyM(m);
	}

	public void rotateZ(float angle){
		Matrix m=Matrix.getRotationZ(angle);
		applyM(m);
	}
	
	public void scale(float scaleX,float scaleY,float scaleZ){
		Matrix m=Matrix.getAmpl(scaleX,scaleY,scaleZ);
		applyM(m);
	}
	
	public void translate3f(float x,float y,float z){
		/* Implements M=(M*(P+newT))+T
		 * 
		 * T' = M*newT+T
		 */
		position.add(this.matrix.Mult(new Vertex3f(x, y, z)));
	}
	
	public void push(){
		Matrix m=new Matrix();
		m.set(this.matrix);
		stackM.push(m);
		Vertex3f v=new Vertex3f();
		v.set(position);
		stackP.push(v);
	}
	
	public void pop(){
		Matrix m=stackM.pop();
		Vertex3f v=stackP.pop();
		if(m!=null && v!=null){
			this.matrix.set(m);
			this.position.set(v);
		}
	}
	
	public float[] asOpenGLMatrix(){
		float[] m={
				matrix.getA(),matrix.getD(),matrix.getG(),0,
				matrix.getB(),matrix.getE(),matrix.getH(),0,
				matrix.getC(),matrix.getF(),matrix.getI(),0,
				position.x,position.y,position.z,1
		};
		return m;
	}
}
